package ca.etsmtl.log430.lab3.sysB;

import java.io.PipedReader;
import java.io.PipedWriter;
import java.util.ArrayList;
import java.util.List;

import javax.swing.text.html.HTMLDocument.Iterator;

/**
 * This class is intended to be a filter that will collect the streams from 
 * two input pipes and merge them into one output pipe.<br><br>
 * 
 * Pseudo Code:
 * <pre>
 * connect to input pipe 1
 * connect to input pipe 2
 * connect to output pipe
 *
 * while not done
 *		read char1 from input pipe 1
 *		read char2 from input pipe 2
 *		string1 = string1 + char1
 *		string2 = string2 + char2
 *		write string1 to output pipe
 *		write string2 to output pipe
 * end while
 *
 * close pipes
 * close file
 * </pre>
 * 
 * @author A.J. Lattanze
 * @version 1.0
 */

public class MergeFilter extends Thread {

	// Create local pipes to that will connect to upstream filters
	List<PipedReader> inputsPipe =  new ArrayList<PipedReader>();

	// Create local pipes to that will connect to downstream filter
	PipedWriter outputPipe= new PipedWriter();

	public MergeFilter(List<PipedWriter> InputsPipe, PipedWriter OutputPipe) {
		try {
			// Connect InputPipes to upstream filters
			java.util.Iterator<PipedWriter> ite = InputsPipe.iterator();
			while(ite.hasNext()){
				PipedReader inputPipe = new PipedReader();
				inputPipe.connect(ite.next());
				this.inputsPipe.add(inputPipe);
			}
			
			System.out.println("MergeFilter:: connected to upstream filters.");
		} catch (Exception Error) {
			System.out.println("MergeFilter:: Error connecting input pipes.");
		}

		try {
			// Connect outputPipe to downstream filter
			this.outputPipe = OutputPipe;
			System.out.println("MergeFilter:: connected to downstream filter.");
		} catch (Exception Error) {
			System.out.println("MergeFilter:: Error connecting output pipe.");
		}
	}

	// This is the method that is called when the thread is started
	public void run() {

		// Begin process data from the input pipes
		try {
			char[] characterValue = new char[1];// Need to be an array for easy conversion to string
			int integerCharacter;// integer values read from the pipes
			String lineOfText = "";// lines of text from input pipes
			boolean write = false;// Indicate whether lines of text are ready to be output to downstream filters


			// Loop for reading data
			java.util.Iterator<PipedReader> ite1 = inputsPipe.iterator();
			while(ite1.hasNext()){
				PipedReader inputPipe = ite1.next();
				boolean done = false;// Flags for reading from each pipe
				
				while (!done) {
					// Read pipe
					integerCharacter = inputPipe.read();
					characterValue[0] = (char) integerCharacter;

					if (integerCharacter == -1) // pipe is closed
					{
						done = true;
						System.out.println("MergeFilter:: Input pipe 1 closed.");

						try {
							inputPipe.close();
						} catch (Exception Error) {
							System.out.println("MergeFilter:: Error closing input pipe 1.");
						}
					} else {
						if (integerCharacter == '\n') // end of line
						{
							System.out.println("MergeFilter:: Received: " + lineOfText + " on input pipe 1.");
							write = true;
						} else {
							lineOfText += new String(characterValue);
						}
					}
					
					if(write == true){
						write = false;
						try {
							System.out.println("MergeFilter:: Sending " + lineOfText + " to output pipe.");
							lineOfText += "\n";
							outputPipe.write(lineOfText, 0, lineOfText.length());
							outputPipe.flush();
						} catch (Exception IOError) {
							System.out.println("MergeFilter:: Write Error.");
						}
						lineOfText = "";	
					}
				}
			}
		}
		catch (Exception Error) {
			System.out.println("MergeFilter:: Interrupted.");
		}

		try {
			outputPipe.close();
			System.out.println("MergeFilter:: output pipe closed.");

		} catch (Exception Error) {
			System.out.println("MergeFilter:: Error closing pipes");
		}
	}
}